package com.hythzx.ddns.service;

import com.aliyuncs.IAcsClient;
import com.aliyuncs.alidns.model.v20150109.AddDomainRecordRequest;
import com.aliyuncs.alidns.model.v20150109.AddDomainRecordResponse;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsRequest;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsResponse;
import com.aliyuncs.alidns.model.v20150109.DescribeDomainRecordsResponse.Record;
import com.aliyuncs.alidns.model.v20150109.UpdateDomainRecordRequest;
import com.aliyuncs.alidns.model.v20150109.UpdateDomainRecordResponse;
import com.aliyuncs.exceptions.ClientException;
import com.hythzx.ddns.config.ApplicationProperties;
import com.hythzx.ddns.config.ApplicationProperties.Dns;
import org.slf4j.Logger;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * @author zhaoyuan
 */
@Service
public class AliyunDnsService {

	private final IpService ipService;

	private final Logger log = getLogger(AliyunDnsService.class);

	private final IAcsClient iAcsClient;

	private static final String RECORD_TYPE_V4 = "A";

	private static final String RECORD_TYPE_V6 = "AAAA";

	private final ApplicationProperties applicationProperties;

	public AliyunDnsService(@Qualifier("ifconfig") IpService ipService, IAcsClient iAcsClient, ApplicationProperties applicationProperties) {
		this.ipService = ipService;
		this.iAcsClient = iAcsClient;
		this.applicationProperties = applicationProperties;
	}

	@Scheduled(fixedRate = 600000)
	public void run(){
		log.info("定时器开始处理DDNS任务...");
		try {
			process();
		}catch (Exception e) {
			log.warn("DDNS处理失败，失败信息是: [{}]-[{}]", e.getCause(), e.getMessage());
		}
		log.info("DDNS定时器完成");
	}

	/**
	 * 定时任务处理
	 * @author zhaoyuan
	 */
	public void process() throws ClientException {
		// 查询指定二级域名的最新解析记录
		DescribeDomainRecordsRequest describeDomainRecordsRequest = new DescribeDomainRecordsRequest();
		for (Dns dns : applicationProperties.getDns()) {
			// 主域名
			describeDomainRecordsRequest.setDomainName(dns.getDomain());
			// 主机记录
			describeDomainRecordsRequest.setRRKeyWord(dns.getKeyword());
			// 解析记录类型
			describeDomainRecordsRequest.setType(dns.getType());
			DescribeDomainRecordsResponse describeDomainRecordsResponse = describeDomainRecords(describeDomainRecordsRequest, iAcsClient);
			String currentIp = ipService.getPublicIp(dns.getType()).orElseThrow(() -> new RuntimeException("获取本机公网IP出错"));
			if (!describeDomainRecordsResponse.getDomainRecords().isEmpty()) {
				Record record = describeDomainRecordsResponse.getDomainRecords().get(0);
				String recordId = record.getRecordId();
				String value = record.getValue();
				log.debug("获取阿里云解析成功，阿里云的记录值是: [{}],本机目前的IP是: [{}]", value, currentIp);
				if (!currentIp.equals(value)) {
					log.info("当前本机的IP({})和阿里云配置的IP({})不一致，修改修改云解析", currentIp, value);
					UpdateDomainRecordRequest updateDomainRecordRequest = new UpdateDomainRecordRequest();
					// 主机记录
					updateDomainRecordRequest.setRR(dns.getKeyword());
					// 记录ID
					updateDomainRecordRequest.setRecordId(recordId);
					// 将主机记录值改为当前主机IP
					updateDomainRecordRequest.setValue(currentIp);
					// 解析记录类型
					updateDomainRecordRequest.setType(dns.getType());
					iAcsClient.getAcsResponse(updateDomainRecordRequest);
					log.info("云解析({}.{})修改完成，新IP是：[{}]", record.getRR(), record.getDomainName(), currentIp);
				}
			} else{
				AddDomainRecordRequest addDomainRecordRequest = new AddDomainRecordRequest();
				addDomainRecordRequest.setTTL(600L);
				addDomainRecordRequest.setRR(dns.getKeyword());
				addDomainRecordRequest.setType(dns.getType());
				addDomainRecordRequest.setDomainName(dns.getDomain());
				addDomainRecordRequest.setValue(currentIp);
				AddDomainRecordResponse addDomainRecordResponse = iAcsClient.getAcsResponse(addDomainRecordRequest);
				log.info("云解析添加完成，返回信息是: [{}]", addDomainRecordResponse);
			}
		}

	}


	/**
	 * 获取主域名的所有解析记录列表
	 */
	private DescribeDomainRecordsResponse describeDomainRecords(DescribeDomainRecordsRequest request, IAcsClient client){
		try {
			// 调用SDK发送请求
			return client.getAcsResponse(request);
		} catch (ClientException e) {
			log.error("DDNS获取主域名的所有解析记录列表失败，失败信息是: [{}]-[{}]", e.getCause(), e.getMessage());
			// 发生调用错误，抛出运行时异常
			throw new RuntimeException();
		}
	}

	/**
	 * 修改解析记录
	 */
	private UpdateDomainRecordResponse updateDomainRecord(UpdateDomainRecordRequest request, IAcsClient client){
		try {
			// 调用SDK发送请求
			return client.getAcsResponse(request);
		} catch (ClientException e) {
			log.error("DDNS修改解析记录失败，失败信息是: [{}]-[{}]", e.getCause(), e.getMessage());
			// 发生调用错误，抛出运行时异常
			throw new RuntimeException();
		}
	}

}
